//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Copyright 2012 Microsoft Corporation. All Rights Reserved
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.   
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

namespace Preflight.ServiceModel.Adapter
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Contract;
    using Model;

    public class ModelTransformer : IModelTransformer 
    {
        public PreflightCheck CreatePreflightCheck(PreflightResult preflightResult, ApplicationDescription applicationDescription)
        {
            if (preflightResult == null)
            {
                throw new ArgumentNullException("preflightResult");
            }

            if (applicationDescription == null)
            {
                throw new ArgumentNullException("applicationDescription");
            }

            var verificationResultsList = preflightResult.VerificationResults.ToList();

            var preflightCheck = new PreflightCheck
                       {
                           Description = CreateDescription(applicationDescription),
                           ExecutedOnUtc = preflightResult.ExecutedOnUtc,
                           Passed = true,
                       };

            SetCategoriesFromVerificationResults(verificationResultsList, preflightCheck);

            return preflightCheck;
        }

        public HostDetails CreateDetails(ApplicationDetail applicationDetail)
        {
            if (applicationDetail == null)
            {
                throw new ArgumentNullException("applicationDetail");
            }

            if (applicationDetail.Description == null)
            {
                throw new ArgumentException("Application description cannot be null");
            }

            return new HostDetails
                       {
                           Description = CreateDescription(applicationDetail.Description),
                           VerificationCategories = GetCategories(applicationDetail.TestCategories),
                           MetaItems = new MetaItemCollection()
                       };
        }

        private static CategoryCollection GetCategories(IEnumerable<string> testCategories)
        {
            if (testCategories == null || testCategories.Any() == false)
            {
                return new CategoryCollection();
            }

            return new CategoryCollection(testCategories);
        }

        private static Description CreateDescription(ApplicationDescription applicationDescription)
        {
            return new Description
                       {
                           Name = applicationDescription.Name,
                           Category = applicationDescription.Category,
                           Version = applicationDescription.Version
                       };
        }

        private static void SetCategoriesFromVerificationResults(IEnumerable<VerificationResult> verificationResults, PreflightCheck preflightCheck)
        {
            var categories = new Dictionary<string, Category>();
            foreach (var result in verificationResults)
            {
                var categoryName = result.VerificationCategory.ToUpperInvariant();
                if (categories.ContainsKey(categoryName) == false)
                {
                    categories[categoryName] = new Category
                                  {
                                      Name = result.VerificationCategory, 
                                      Verifications = new List<Verification>()
                                  };
                }

                var verification = CreateVerification(result);
                categories[categoryName].Verifications.Add(verification);

                if (result.Passed == false)
                {
                    preflightCheck.Passed = false; 
                }
            }

            preflightCheck.Categories = categories.Values.ToList();
        }

        private static Verification CreateVerification(VerificationResult result)
        {
            return new Verification
                       {
                           Name = result.VerificationName,
                           Passed = result.Passed,
                           Messages =
                               result.Messages.Select(
                                   item =>
                                   new PreflightMessage
                                       {
                                           Content = item.Content, 
                                           Type = GetMessageType(item.MessageType)
                                       })
                               .ToList()
                       };
        }

        private static PreflightMessageType GetMessageType(MessageType messageType)
        {
            switch (messageType)
            {
                case MessageType.Error:
                    return PreflightMessageType.Error;
                case MessageType.Warning:
                    return PreflightMessageType.Warning;
                default:
                    return PreflightMessageType.Information;
            }
        }
    }
}
